package com.wargon.securitycommon.util;

import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;

import java.sql.Date;
import java.text.ParseException;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;

public class JWTUtils {

    public static String getJWT(String username, String issuer, RSAKey rsaKey, Duration duration, Map<String, Object> claim) throws JOSEException {
        JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
                .subject(username)
                .issuer(issuer)
                .issueTime(Date.from(Instant.now()))
                .expirationTime(Date.from(Instant.now().plus(duration)))
                .claim("claim",claim)
                .build();
        SignedJWT signedJWT = new SignedJWT(
                new JWSHeader.Builder(JWSAlgorithm.RS256)
                        .type(JOSEObjectType.JWT)
                        .keyID(rsaKey.getKeyID()).build(),
                claimsSet
        );
        JWSSigner signer = new RSASSASigner(rsaKey);
        signedJWT.sign(signer);

        String jwt = signedJWT.serialize();

        return jwt;
    }

    public static JWTClaimsSet getClaimSet(String jwt, RSAKey rsaKey) throws ParseException, JOSEException {
        SignedJWT signedJWT = SignedJWT.parse(jwt);
        JWSVerifier verifier = new RSASSAVerifier(rsaKey);
        if(!signedJWT.verify(verifier)) {
            throw new JOSEException("Invalid JWT Signature");
        }
        //verify expire date
        if(signedJWT.getJWTClaimsSet().getExpirationTime().before(new java.util.Date())) {
            throw new JOSEException("JWT Expired");
        }
        return signedJWT.getJWTClaimsSet();
    }

    public static String getUsername(String jwt, RSAKey rsaKey) throws ParseException, JOSEException {
        return getClaimSet(jwt,rsaKey).getSubject();
    }
}
